from time import clock

class GameRunner():
    '''
    Runs a game.
    '''
    
    def __init__(self, initial_state, agents, turn_time_limit, setup_time_limit):
        '''
        Constructor.
        
        @param initial_state: The initial game q_state.
        @param agents: A dictionary that maps players to their agents.
        @param turn_time_limit: The time limit of each turn.
        @param setup_time_limit: The time limit for setting up the agent.
        '''
        self.initial_state = initial_state
        self.agents = agents
        self.turn_time_limit = turn_time_limit
        self.setup_time_limit = setup_time_limit
    
    def run(self):
        '''
        Runs the game. Prints actions and states.
        
        @return: The game's winner.
        '''
        total_step_num = 0
        for player, agent in self.agents.items():
            start = clock()
            agent.setup(player, self.initial_state, self.turn_time_limit, self.setup_time_limit)
            setup_time = clock() - start
            if setup_time > self.setup_time_limit:
                raise Exception(str(player) + ' failed to set up in time.')
        
        q_state = self.initial_state
        while q_state.getWinner() is None:
            agent = self.agents[q_state.getCurrentPlayer()]
            start = clock()
            action = agent.move(q_state)
            turn_time = clock() - start
            print "Move time: ", turn_time
            if turn_time > self.turn_time_limit:
#                print "**WARNING:time limits are disabled!!"
                raise Exception(str(q_state.getCurrentPlayer()) + ' failed to return a move in time.')
            
            successors = q_state.getSuccessors()
            if action not in successors.keys():
                raise Exception(str(q_state.getCurrentPlayer()) + ' made an illegal move.')
            
            q_state = successors[action]
            
            total_step_num += 1
            
            print action
            print q_state
        
        print "Total steps number: ", total_step_num
        
        '''for player, agent in self.agents.items():
            tot = agent.alphaBeta.cache_cnt + agent.alphaBeta.non_cache_cnt
            print "player %s used cache %s times of %s (%%%s)" % (player, agent.alphaBeta.cache_cnt, agent.alphaBeta.non_cache_cnt, agent.alphaBeta.cache_cnt*100. /tot)
        '''
        return q_state.getWinner(), total_step_num
 